<?php
namespace rrx\sdk;

use Exception;

class RrxApi
{
    protected $config = [];

    private $baseUrl = 'https://open.rrx.cn/api';

    /**
     * 构造方法
     * @param array $config
     * @throws Exception
     */
    public function __construct($config)
    {
        if (!isset($config['secret'])) throw new Exception('secret不能为空');
        $this->config = $config;
        if (isset($config['baseUrl'])) {
            $this->baseUrl = $config['baseUrl'];
        }
    }

    public function buildParamsUri($params)
    {
        if (empty($params['time_stamp'])) {
            $params['time_stamp'] = getMicroTime();
        }
        $params['sign'] = self::makeSign($params);
        return Common::arrToUri($params);
    }

    /**
     * @throws Exception
     */
    public function checkSign($params)
    {
        $this->checkCommonParams($params);
        $timeStamp = $params['time_stamp'];
        $overTime = 60 * 5; // 五分钟 默认
        $cha = (getMicroTime() - $timeStamp) / 1000;
        if ($cha > $overTime) {
            throw new Exception('签名已过期', 1);
        }

        $sign = $this->makeSign($params);
        if ($sign != $params['sign']) {
            throw new Exception('签名错误');
        }
        return true;
    }

    /**
     * 校验参数
     * @throws Exception
     */
    private function checkCommonParams($params)
    {
        if (!isset($params['app_key'])) {
            throw new Exception('缺少参数 app_key', 1);
        }
        if (!isset($params['time_stamp'])) {
            throw new Exception('缺少参数 time_stamp');
        }
        if (!isset($params['sign'])) {
            throw new Exception('缺少参数 sign', 1);
        }
    }

    /**
     * 签名生成算法
     * @param $params
     * @return string
     */
    public function makeSign($params)
    {
        if (!empty($params['sign'])) {
            unset($params['sign']);
        }
        // 签名步骤一：按字典序排序参数
        ksort($params);
        $string = Common::arrToUri($params, false);
        // 签名步骤二：在string后加入app_secret
        $string = $string . "&app_secret=" . $this->config['secret'];
        // 签名步骤三：MD5加密
        $string = md5($string);
        // 签名步骤四：所有字符转为大写
        return strtoupper($string);
    }

    /**
     * @throws Exception
     */
    protected function sendRequest($endpoint, $params, $type = 'get', $toJson = true)
    {
        // 补全请求参数
        $params['time_stamp'] = getMicroTime();
        $params['sign'] = $this->makeSign($params);

        // 发送请求
        // 判断字符串$endpoint第一个字符是否是/，不是则拼接/
        $endpoint = $endpoint[0] == '/' ? $endpoint : '/' . $endpoint;
        $url = $this->baseUrl . $endpoint;
        return Common::sendHTTP($url, $params, $type, $toJson);
    }

    /**
     * 通用获取列表
     * @param string $endpoint
     * @param string $activity_guid
     * @param string $h5_guid
     * @param int $page
     * @param int $limit
     * @param string $start_time
     * @param string $end_time
     * @param string $openid
     * @param string $share_openid
     * @return mixed
     * @throws Exception
     */
    protected function commonGetList($endpoint, $activity_guid, $h5_guid = '', $page = 1, $limit = 20, $start_time = '', $end_time = '', $openid = '', $share_openid = '')
    {
        if (!is_numeric($page) || $page < 1) {
            throw new Exception('page分页页面只能是数字');
        }
        if (!is_numeric($limit) || $limit < 1) {
            throw new Exception('limit每页返回数量只能是数字');
        }

        if ($start_time && (!is_string($start_time) || !strtotime($start_time))) {
            throw new Exception('start_time格式错误');
        }
        if ($end_time && (!is_string($end_time) || !strtotime($end_time))) {
            throw new Exception('end_time格式错误');
        }

        $params = [
            'app_key' => $this->config['app_key'],
            'activity_guid' => $activity_guid,
            'h5_guid' => $h5_guid,
            'page' => $page,
            'limit' => $limit,
            'start_time' => $start_time,
            'end_time' => $end_time,
            'openid' => $openid,
            'share_openid' => $share_openid,
        ];
        return $this->sendRequest($endpoint, $params);
    }
}